import os
import uuid
import re
from sqlalchemy.orm import Session
from .models import ResourceCategory, ResourceDetails, ResourceEntitiesMap, RelationshipDefinition
from langchain.docstore.document import Document
from typing import List, Dict, Any

class ImprovedDataProcessor:
    def __init__(self, db: Session):
        self.db = db
    
    def get_all_resource_categories(self) -> List[Dict[str, Any]]:
        """获取所有资源类别数据"""
        categories = self.db.query(ResourceCategory).all()
        result = []
        for category in categories:
            result.append({
                'id': category.id,
                'name': category.category_name,
                'code': category.category_code,
                'description': category.description,
                'color': category.color,
                'icon': category.icon
            })
        return result
    
    def get_all_resource_details(self) -> List[Dict[str, Any]]:
        """获取所有资源节点数据"""
        resources = self.db.query(ResourceDetails).all()
        result = []
        for resource in resources:
            result.append({
                'id': resource.id,
                'name': resource.details_name,
                'category_id': resource.category_id,
                'host': resource.host,
                'description': resource.description,
                'annotations': resource.annotations
            })
        return result
    
    def get_all_relationships(self) -> List[Dict[str, Any]]:
        """获取所有关系数据"""
        maps = self.db.query(ResourceEntitiesMap).all()
        result = []
        
        for map_entry in maps:
            # 获取关系定义
            relationship_def = self.db.query(RelationshipDefinition).filter_by(id=map_entry.relation_id).first()
            relationship_name = relationship_def.name if relationship_def else '未知关系'
            
            # 获取起始节点和结束节点
            start_node = self.db.query(ResourceDetails).filter_by(id=map_entry.start_nodes_id).first()
            end_node = self.db.query(ResourceDetails).filter_by(id=map_entry.end_nodes_id).first()
            
            result.append({
                'id': map_entry.id,
                'start_node_id': map_entry.start_nodes_id,
                'end_node_id': map_entry.end_nodes_id,
                'start_node_name': start_node.details_name if start_node else '未知节点',
                'end_node_name': end_node.details_name if end_node else '未知节点',
                'relationship_name': relationship_name
            })
        
        return result
    
    def build_knowledge_graph(self) -> Dict[str, Any]:
        """构建知识图谱数据"""
        nodes = self.get_all_resource_details()
        edges = self.get_all_relationships()
        
        # 获取所有节点的ID集合，用于快速查找
        node_ids = set(node['id'] for node in nodes)
        
        # 过滤掉引用不存在节点的关系
        filtered_edges = [
            edge for edge in edges 
            if edge['start_node_id'] in node_ids and edge['end_node_id'] in node_ids
        ]
        
        graph_data = {
            'nodes': nodes,
            'edges': filtered_edges
        }
        
        return graph_data
    
    def search_resources_by_category(self, category_name: str) -> List[Dict[str, Any]]:
        """根据类别名称搜索资源节点"""
        # 先查找类别
        category = self.db.query(ResourceCategory).filter(
            ResourceCategory.category_name == category_name
        ).first()
        
        if not category:
            return []
        
        # 根据类别ID查找所有资源
        resources = self.db.query(ResourceDetails).filter(
            ResourceDetails.category_id == category.id
        ).all()
        
        result = []
        for resource in resources:
            result.append({
                'id': resource.id,
                'name': resource.details_name,
                'description': resource.description,
                'category_id': resource.category_id,
                'category_name': category_name
            })
        
        return result
    
    def extract_entities_from_query(self, query: str) -> List[str]:
        """从查询中提取实体名称"""
        # 获取所有资源名称作为参考
        all_resources = self.get_all_resource_details()
        resource_names = [resource['name'] for resource in all_resources]
        
        # 查找查询中包含的完整资源名称
        matched_entities = []
        for name in resource_names:
            if name in query:
                matched_entities.append(name)
        
        # 特殊处理包含关键词的查询
        if not matched_entities:
            # 处理包含'test'的查询
            if 'test' in query.lower():
                matched_entities.extend([name for name in resource_names if '测试' in name])
            
            # 处理包含'94'的查询
            if '94' in query:
                matched_entities.extend([name for name in resource_names if '94' in name])
            
            # 处理包含'tomcat'的查询
            if 'tomcat' in query.lower():
                matched_entities.extend([name for name in resource_names if 'tomcat' in name.lower()])
        
        # 如果仍然没有找到匹配，使用关键词搜索
        if not matched_entities:
            # 移除常见的停用词和疑问词
            stop_words = ['什么', '如何', '为什么', '哪个', '哪里', '有没有', '是否', '关系', '有', '和', '与', '及', '以及', '或者', '还是', '查找', '搜索', '所有', '包含', '名称', '节点', '资源', '相关', '通过', '连接', '开始', '间接', '关联', '服务器', '运行', '应用', '系统', '服务', '环境', '相关', '上游', '下游', '依赖']
            
            # 尝试不同的关键词提取方法
            # 方法1: 直接匹配资源名称中的部分字符串
            for name in resource_names:
                # 移除特殊字符进行模糊匹配
                clean_name = re.sub(r'[^\w\u4e00-\u9fff]', '', name)  # 保留中文、英文和数字
                clean_query = re.sub(r'[^\w\u4e00-\u9fff]', '', query)
                if clean_name in clean_query or clean_query in clean_name:
                    matched_entities.append(name)
            
            # 方法2: 关键词分割匹配
            if not matched_entities:
                # 使用更智能的关键词提取方法
                words = query.split()
                
                # 过滤停用词
                filtered_words = [word for word in words if word not in stop_words]
                
                # 尝试组合相邻的词来匹配资源名称
                for i in range(len(filtered_words)):
                    # 单个词匹配
                    matched_entities.extend([name for name in resource_names if filtered_words[i] in name])
                    
                    # 双词组合匹配
                    if i < len(filtered_words) - 1:
                        two_word = f"{filtered_words[i]}{filtered_words[i+1]}"
                        matched_entities.extend([name for name in resource_names if two_word in name])
                    
                    # 三词组合匹配
                    if i < len(filtered_words) - 2:
                        three_word = f"{filtered_words[i]}{filtered_words[i+1]}{filtered_words[i+2]}"
                        matched_entities.extend([name for name in resource_names if three_word in name])
        
        # 去重
        unique_entities = list(set(matched_entities))
        return unique_entities
    
    def search_resources_by_keyword(self, keyword: str) -> List[Dict[str, Any]]:
        """根据关键词搜索资源节点"""
        # 使用SQLAlchemy的like操作符进行模糊搜索
        resources = self.db.query(ResourceDetails).filter(
            ResourceDetails.details_name.like(f'%{keyword}%') | 
            ResourceDetails.description.like(f'%{keyword}%') |
            ResourceDetails.annotations.like(f'%{keyword}%')
        ).all()
        
        result = []
        for resource in resources:
            result.append({
                'id': resource.id,
                'name': resource.details_name,
                'description': resource.description,
                'category_id': resource.category_id
            })
        
        return result
    
    def search_resources_by_name(self, name: str) -> List[Dict[str, Any]]:
        """根据资源名称精确搜索资源节点"""
        resources = self.db.query(ResourceDetails).filter(
            ResourceDetails.details_name == name
        ).all()
        
        result = []
        for resource in resources:
            result.append({
                'id': resource.id,
                'name': resource.details_name,
                'description': resource.description,
                'category_id': resource.category_id
            })
        
        return result
    
    def get_resource_by_id(self, resource_id: str) -> Dict[str, Any]:
        """根据资源ID获取资源详情"""
        resource = self.db.query(ResourceDetails).filter_by(id=resource_id).first()
        if not resource:
            return None
        
        # 获取资源类别信息
        category = self.db.query(ResourceCategory).filter_by(id=resource.category_id).first()
        
        return {
            'id': resource.id,
            'name': resource.details_name,
            'description': resource.description,
            'category_id': resource.category_id,
            'category_name': category.category_name if category else None,
            'host': resource.host,
            'annotations': resource.annotations,
            'create_time': resource.create_time.isoformat() if resource.create_time else None,
            'update_time': resource.update_time.isoformat() if resource.update_time else None
        }
    
    def find_related_resources(self, resource_id: str, depth: int = 1) -> List[Dict[str, Any]]:
        """查找与指定资源相关的其他资源（多跳查询）"""
        visited = set()
        related_resources = []
        
        def dfs(current_id: str, current_depth: int):
            if current_id in visited or current_depth > depth:
                return
            
            visited.add(current_id)
            
            # 查找从当前节点出发的关系
            outgoing_relationships = self.db.query(ResourceEntitiesMap).filter_by(start_nodes_id=current_id).all()
            for rel in outgoing_relationships:
                end_node = self.db.query(ResourceDetails).filter_by(id=rel.end_nodes_id).first()
                if end_node and end_node.id not in visited:
                    relationship_def = self.db.query(RelationshipDefinition).filter_by(id=rel.relation_id).first()
                    related_resources.append({
                        'id': end_node.id,
                        'name': end_node.details_name,
                        'type': 'outgoing',
                        'relationship': relationship_def.name if relationship_def else '未知关系'
                    })
                    dfs(end_node.id, current_depth + 1)
            
            # 查找指向当前节点的关系
            incoming_relationships = self.db.query(ResourceEntitiesMap).filter_by(end_nodes_id=current_id).all()
            for rel in incoming_relationships:
                start_node = self.db.query(ResourceDetails).filter_by(id=rel.start_nodes_id).first()
                if start_node and start_node.id not in visited:
                    relationship_def = self.db.query(RelationshipDefinition).filter_by(id=rel.relation_id).first()
                    related_resources.append({
                        'id': start_node.id,
                        'name': start_node.details_name,
                        'type': 'incoming',
                        'relationship': relationship_def.name if relationship_def else '未知关系'
                    })
                    dfs(start_node.id, current_depth + 1)
        
        # 开始深度优先搜索
        dfs(resource_id, 0)
        
        return related_resources
    
    def find_relationship_between_resources(self, resource1_name: str, resource2_name: str) -> List[Dict[str, Any]]:
        """查找两个资源之间的关系"""
        # 获取资源详情
        resource1 = self.db.query(ResourceDetails).filter_by(details_name=resource1_name).first()
        resource2 = self.db.query(ResourceDetails).filter_by(details_name=resource2_name).first()
        
        if not resource1 or not resource2:
            return []
        
        # 查找从resource1到resource2的关系
        relationships_1_to_2 = self.db.query(ResourceEntitiesMap).filter_by(
            start_nodes_id=resource1.id, 
            end_nodes_id=resource2.id
        ).all()
        
        # 查找从resource2到resource1的关系
        relationships_2_to_1 = self.db.query(ResourceEntitiesMap).filter_by(
            start_nodes_id=resource2.id, 
            end_nodes_id=resource1.id
        ).all()
        
        result = []
        
        # 处理resource1到resource2的关系
        for rel in relationships_1_to_2:
            relationship_def = self.db.query(RelationshipDefinition).filter_by(id=rel.relation_id).first()
            result.append({
                'from': resource1.details_name,
                'to': resource2.details_name,
                'relationship': relationship_def.name if relationship_def else '未知关系',
                'direction': 'forward'
            })
        
        # 处理resource2到resource1的关系
        for rel in relationships_2_to_1:
            relationship_def = self.db.query(RelationshipDefinition).filter_by(id=rel.relation_id).first()
            result.append({
                'from': resource2.details_name,
                'to': resource1.details_name,
                'relationship': relationship_def.name if relationship_def else '未知关系',
                'direction': 'reverse'
            })
        
        return result
    
    def build_context_for_qa(self, query: str) -> List[Document]:
        """为问答系统构建上下文文档"""
        print(f"开始处理查询: {query}")
        
        # 1. 使用改进的实体提取方法
        entities = self.extract_entities_from_query(query)
        print(f"从查询'{query}'中提取到实体: {entities}")
        
        all_relevant_resources = []
        
        # 2. 对每个实体进行精确搜索
        for entity in entities:
            resources = self.search_resources_by_name(entity)
            all_relevant_resources.extend(resources)
            if resources:
                print(f"通过精确搜索找到 {len(resources)} 个资源: {entity}")
        
        # 3. 如果没有找到精确匹配，使用关键词搜索
        if not all_relevant_resources:
            keywords = query.split()
            for keyword in keywords:
                # 跳过常见的停用词
                stop_words = ['什么', '如何', '为什么', '哪个', '哪里', '有没有', '是否', '关系', '有', '和', '与', '及', '以及', '或者', '还是']
                if keyword not in stop_words:
                    resources = self.search_resources_by_keyword(keyword)
                    all_relevant_resources.extend(resources)
                    if resources:
                        print(f"通过关键词搜索找到 {len(resources)} 个资源: {keyword}")
        
        # 4. 特殊处理类别相关的查询
        print(f"开始处理类别相关的查询: {query}")
        category_resources_found = False
        
        # 更全面的类别匹配模式
        import re
        category_patterns = [
            r'类别[是为](.*?)[的有]',  # 类别是xxx的/类别为xxx的
            r'类别[是为](.*?)[？?]?$',  # 类别是xxx结尾
            r'(.*?)类别的',  # xxx类别的
            r'(.*?)类型的',  # xxx类型的
            r'所有(.*?)资源',  # 所有xxx资源
            r'(.*?)服务器有哪些',  # xxx服务器有哪些
            r'(.*)有哪些',  # xxx有哪些
            r'(.*)列表',  # xxx列表
        ]
        
        for pattern in category_patterns:
            matches = re.findall(pattern, query, re.IGNORECASE)
            print(f"使用模式 '{pattern}' 找到匹配: {matches}")
            for match in matches:
                if match and len(match.strip()) > 1:  # 过滤掉太短的匹配
                    category_name = match.strip()
                    print(f"尝试根据类别名称搜索资源: {category_name}")
                    # 根据类别名称搜索资源
                    category_resources = self.search_resources_by_category(category_name)
                    if category_resources:
                        all_relevant_resources.extend(category_resources)
                        category_resources_found = True
                        print(f"通过类别查询找到 {len(category_resources)} 个资源，类别: {category_name}")
                    else:
                        print(f"未找到类别 '{category_name}' 的资源")
        
        # 5. 如果仍然没有找到相关资源，尝试更广泛的类别匹配
        if not category_resources_found:
            print("尝试更广泛的类别匹配")
            # 查找查询中可能的类别关键词
            category_keywords = ['centos', 'docker', 'kubernetes', 'linux', 'windows', 'tomcat', 'nginx', 'mysql', 'redis']
            query_lower = query.lower()
            
            for keyword in category_keywords:
                if keyword in query_lower:
                    print(f"在查询中找到关键词: {keyword}")
                    # 尝试不同的类别名称变体
                    # 首先尝试直接从数据库中查找包含该关键词的所有类别
                    from sqlalchemy import or_
                    from .models import ResourceCategory  # 导入正确的模型
                    matching_categories = self.db.query(ResourceCategory).filter(
                        or_(
                            ResourceCategory.category_name.contains(keyword),
                            ResourceCategory.category_name.contains(keyword.capitalize()),
                            ResourceCategory.category_name.contains(keyword.upper())
                        )
                    ).all()
                    
                    print(f"找到 {len(matching_categories)} 个匹配的类别")
                    
                    # 对于每个匹配的类别，获取其下的资源
                    for category in matching_categories:
                        print(f"尝试类别: {category.category_name}")
                        category_resources = self.search_resources_by_category(category.category_name)
                        if category_resources:
                            all_relevant_resources.extend(category_resources)
                            category_resources_found = True
                            print(f"通过类别查询找到 {len(category_resources)} 个资源，类别: {category.category_name}")
                        else:
                            print(f"未找到类别 '{category.category_name}' 的资源")
                    
                    # 如果上面的方法没找到，再尝试一些常见的变体
                    if not category_resources_found:
                        variations = [keyword, keyword.capitalize(), keyword.upper(), 
                                    f"操作系统-{keyword.capitalize()}", 
                                    f"应用-{keyword.capitalize()}",
                                    f"云原生-{keyword.capitalize()}",
                                    f"操作系统-{keyword.capitalize()} Linux",
                                    f"应用服务-{keyword.capitalize()}"]
                        
                        for variation in variations:
                            print(f"尝试类别变体: {variation}")
                            category_resources = self.search_resources_by_category(variation)
                            if category_resources:
                                all_relevant_resources.extend(category_resources)
                                category_resources_found = True
                                print(f"通过关键词变体查询找到 {len(category_resources)} 个资源，类别: {variation}")
                                break
                            else:
                                print(f"未找到类别 '{variation}' 的资源")
        
        # 去重
        unique_resources = list({resource['id']: resource for resource in all_relevant_resources}.values())
        print(f"去重后共有 {len(unique_resources)} 个唯一资源")
        
        # 6. 为每个相关资源获取其相关资源（多跳）
        context_docs = []
        
        for resource in unique_resources:
            # 创建资源本身的文档
            resource_text = f"资源名称: {resource['name']}\n描述: {resource['description']}\n"
            # 如果有类别信息，也添加到文档中
            if 'category_name' in resource:
                resource_text = f"资源名称: {resource['name']}\n类别: {resource['category_name']}\n描述: {resource['description']}\n"
            
            context_docs.append(Document(page_content=resource_text, metadata={'source': 'resource', 'id': resource['id']}))
            
            # 获取与该资源相关的资源
            related_resources = self.find_related_resources(resource['id'], depth=1)
            
            for related in related_resources:
                # 获取相关资源的详细信息
                related_detail = self.db.query(ResourceDetails).filter_by(id=related['id']).first()
                if related_detail:
                    related_text = f"资源名称: {related_detail.details_name}\n描述: {related_detail.description}\n与{resource['name']}的关系: {related['relationship']}\n"
                    context_docs.append(Document(page_content=related_text, metadata={'source': 'related_resource', 'id': related['id']}))
        
        # 7. 特殊处理关系查询
        if "关系" in query or "关联" in query:
            # 提取查询中的两个实体
            entities = self.extract_entities_from_query(query)
            if len(entities) >= 2:
                # 查找两个实体之间的关系
                relationships = self.find_relationship_between_resources(entities[0], entities[1])
                if relationships:
                    relationship_text = f"实体关系信息:\n"
                    for rel in relationships:
                        relationship_text += f"{rel['from']} --({rel['relationship']})--> {rel['to']}\n"
                    
                    context_docs.append(Document(page_content=relationship_text, metadata={'source': 'relationship', 'type': 'direct'}))
        
        print(f"最终构建了 {len(context_docs)} 个上下文文档")
        return context_docs
    
    def process_query(self, query: str, graph_data: Dict[str, Any], llm_wrapper) -> Dict[str, Any]:
        """处理用户查询并返回结果"""
        try:
            # 构建上下文文档
            context_docs = self.build_context_for_qa(query)
            
            # 如果没有找到相关上下文，返回默认响应
            if not context_docs:
                return {
                    'query': query,
                    'answer': "抱歉，我没有找到与您的查询相关的信息。",
                    'context': []
                }
            
            # 将上下文文档转换为文本
            context_text = "\n".join([doc.page_content for doc in context_docs])
            
            # 构造提示词
            prompt = f"""
            基于以下上下文信息，回答用户的问题。
            
            上下文信息：
            {context_text}
            
            用户问题：{query}
            
            请提供一个准确、简洁的回答：
            """
            
            # 使用LLM生成回答
            answer = llm_wrapper.generate_text(prompt)
            
            # 返回结果
            return {
                'query': query,
                'answer': answer,
                'context': [doc.page_content for doc in context_docs]
            }
        except Exception as e:
            # 如果处理过程中出现错误，返回错误信息
            return {
                'query': query,
                'answer': f"处理查询时发生错误: {str(e)}",
                'context': []
            }